﻿#region copyright
//------------------------------------------------------------------------------
//  此代码版权声明为全文件覆盖，如有原作者特别声明，会在下方手动补充
//  此代码版权（除特别声明外的代码）归作者本人Diego所有
//  源代码使用协议遵循本仓库的开源协议及附加协议
//  Gitee源代码仓库：https://gitee.com/diego2098/ThingsGateway
//  Github源代码仓库：https://github.com/kimdiego2098/ThingsGateway
//  使用文档：https://diego2098.gitee.io/thingsgateway-docs/
//  QQ群：605534569
//------------------------------------------------------------------------------
#endregion

using BlazorComponent;

using Masa.Blazor;

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

using Newtonsoft.Json.Linq;

using System.Collections.Generic;

using ThingsGateway.Foundation.Adapter.OPCDA;
using ThingsGateway.Foundation.Adapter.OPCDA.Da;

namespace ThingsGateway.Foundation.Demo;

/// <summary>
/// OPCDA调试页面
/// </summary>
public partial class OPCDAClientDebugPage : IDisposable
{
    private ThingsGateway.Foundation.Adapter.OPCDA.OPCDAClient _plc;
    private DriverDebugUIPage driverDebugUIPage;
    bool IsShowImportVariableList;
    private OPCDAClientPage opcDAClientPage;
    private OPCDAImportVariable ImportVariable { get; set; }
    [Inject]
    private InitTimezone InitTimezone { get; set; }

    [Inject]
    IPopupService PopupService { get; set; }

    /// <inheritdoc/>
    public void Dispose()
    {
        _plc.SafeDispose();
        opcDAClientPage.SafeDispose();
    }

    /// <inheritdoc/>
    public override string ToString()
    {
        return nameof(OPCDAClient);
    }

    /// <inheritdoc/>
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            if (opcDAClientPage != null)
            {
                opcDAClientPage.LogAction = driverDebugUIPage.LogOut;
                opcDAClientPage.ValueAction = ValueOut;

            }
            _plc = opcDAClientPage.OPC;
            //载入配置
            StateHasChanged();
            driverDebugUIPage.Sections.Clear();
        }

        base.OnAfterRender(firstRender);
    }

    private void Add()
    {
        var tags = new Dictionary<string, List<OpcItem>>();
        var tag = new OpcItem(driverDebugUIPage.Address);
        tags.Add(Guid.NewGuid().ToString(), new List<OpcItem>() { tag });
        try
        {
            _plc.AddItems(tags);
        }
        catch (Exception ex)
        {
            driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {ex}"));
        }
    }

#if Plugin
    private bool isDownLoading;
    private async Task DeviceImport()
    {
        isDownLoading = true;
        await InvokeAsync(StateHasChanged);
        try
        {

            var data = ImportVariable?.GetImportVariableList();
            if (data != null)
            {
                if (data?.Item2?.Count == 0)
                {
                    await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
                    return;
                }
                await Furion.App.GetService<CollectDeviceService>().AddAsync(data?.Item1);
                await Furion.App.GetService<VariableService>().AddBatchAsync(data?.Item2);
                await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
            }
        }
        finally
        {
            isDownLoading = false;
        }
    }
    private IJSObjectReference JSObjectReference;

    /// <inheritdoc/>
    [Inject]
    protected IJSRuntime JSRuntime { get; set; }
    private async Task DownDeviceExport()
    {
        isDownLoading = true;
        await InvokeAsync(StateHasChanged);
        try
        {
            var data = ImportVariable?.GetImportVariableList();
            if (data != null)
            {
                if (data?.Item2?.Count == 0)
                {
                    await PopupService.EnqueueSnackbarAsync("无可用变量", AlertTypes.Warning);
                    return;
                }

                await DownDeviceExportAsync(data?.Item1);
                await DownDeviceVariableExportAsync(data?.Item2, data?.Item1.Name);
                await PopupService.EnqueueSnackbarAsync("成功", AlertTypes.Success);
            }
        }
        finally
        {
            isDownLoading = false;
        }
    }
    /// <summary>
    /// 导出到excel
    /// </summary>
    /// <returns></returns>
    public async Task DownDeviceExportAsync(CollectDevice data)
    {
        using var memoryStream = await Furion.App.GetService<CollectDeviceService>().ExportFileAsync(new List<CollectDevice>() { data });
        using var streamRef = new DotNetStreamReference(stream: memoryStream);
        JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
        await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"设备导出{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
    }

    /// <summary>
    /// 导出到excel
    /// </summary>
    /// <returns></returns>
    public async Task DownDeviceVariableExportAsync(List<DeviceVariable> data, string devName)
    {
        using var memoryStream = await Furion.App.GetService<VariableService>().ExportFileAsync(data, devName);
        using var streamRef = new DotNetStreamReference(stream: memoryStream);
        JSObjectReference ??= await JSRuntime.LoadModuleAsync("js/downloadFileFromStream");
        await JSObjectReference.InvokeVoidAsync("downloadFileFromStream", $"变量导出{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx", streamRef);
    }

#endif

    private Task ReadAsync()
    {
        try
        {
            _plc.ReadItemsWithGroup();

        }
        catch (Exception ex)
        {
            driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - {ex}"));
        }

        return Task.CompletedTask;
    }
    private void Remove()
    {
        _plc.RemoveItems(new List<string>() { driverDebugUIPage.Address });
    }

    private void ValueOut(List<ItemReadResult> values)
    {
        driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Debug, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + values.ToJsonString()));
        if (driverDebugUIPage.Messages.Count > 2500)
        {
            driverDebugUIPage.Messages.Clear();
        }
    }

    private Task WriteAsync()
    {
        try
        {
            JToken tagValue = driverDebugUIPage.WriteValue.GetJTokenFromObj();
            var obj = tagValue.GetObjFromJToken();

            var data = _plc.WriteItem(
                new()
                {
                    {driverDebugUIPage.Address,  obj}
                }
                );
            if (data.Count > 0)
            {
                foreach (var item in data)
                {
                    driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Warning, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - " + item.ToJsonString()));
                }
            }
            else
            {
                driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Information, DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset) + " - 写入成功"));
            }
        }
        catch (Exception ex)
        {
            driverDebugUIPage.Messages.Add((Microsoft.Extensions.Logging.LogLevel.Error, $"{DateTimeExtensions.CurrentDateTime.ToDefaultDateTimeFormat(InitTimezone.TimezoneOffset)} - 写入失败：{ex}"));
        }

        return Task.CompletedTask;
    }
}